using System;
using System.Threading.Tasks;
using wicpowerTcpTool.Network;

namespace wicpowerTcpTool.Models
{
    /// <summary>
    /// 转发组类，管理一对TCP服务器之间的数据转发
    /// </summary>
    public class ForwardGroup : IDisposable
    {
        private readonly TcpServer server1;
        private readonly TcpServer server2;
        private bool isDisposed;

        /// <summary>
        /// 转发组ID
        /// </summary>
        public int Id { get; }

        /// <summary>
        /// 监听端口1
        /// </summary>
        public int Port1 => server1.Port;

        /// <summary>
        /// 转发端口2
        /// </summary>
        public int Port2 => server2.Port;

        /// <summary>
        /// 备注信息
        /// </summary>
        public string Remark { get; }

        /// <summary>
        /// 服务器1的运行状态
        /// </summary>
        public bool IsServer1Running => server1.IsRunning;

        /// <summary>
        /// 服务器2的运行状态
        /// </summary>
        public bool IsServer2Running => server2.IsRunning;

        /// <summary>
        /// 服务器1的客户端连接状态
        /// </summary>
        public bool IsClient1Connected => server1.IsClientConnected;

        /// <summary>
        /// 服务器2的客户端连接状态
        /// </summary>
        public bool IsClient2Connected => server2.IsClientConnected;

        // 事件
        public event EventHandler<bool> Server1StatusChanged;
        public event EventHandler<bool> Server2StatusChanged;
        public event EventHandler<bool> Client1StatusChanged;
        public event EventHandler<bool> Client2StatusChanged;
        public event EventHandler<Exception> ErrorOccurred;
        public event EventHandler DataTransferred;

        /// <summary>
        /// 构造函数
        /// </summary>
        public ForwardGroup(int id, int port1, int port2, string remark)
        {
            Id = id;
            Remark = remark;

            server1 = new TcpServer(port1);
            server2 = new TcpServer(port2);

            // 绑定事件处理
            server1.ConnectionStatusChanged += (s, connected) => Client1StatusChanged?.Invoke(this, connected);
            server2.ConnectionStatusChanged += (s, connected) => Client2StatusChanged?.Invoke(this, connected);
            
            server1.DataReceived += async (s, data) =>
            {
                await server2.SendDataAsync(data);
                DataTransferred?.Invoke(this, EventArgs.Empty);
            };

            server2.DataReceived += async (s, data) =>
            {
                await server1.SendDataAsync(data);
                DataTransferred?.Invoke(this, EventArgs.Empty);
            };

            server1.ErrorOccurred += (s, ex) => ErrorOccurred?.Invoke(this, ex);
            server2.ErrorOccurred += (s, ex) => ErrorOccurred?.Invoke(this, ex);
        }

        /// <summary>
        /// 启动转发服务
        /// </summary>
        public void Start()
        {
            if (isDisposed)
                throw new ObjectDisposedException(nameof(ForwardGroup));

            try
            {
                server1.Start();
                Server1StatusChanged?.Invoke(this, true);

                server2.Start();
                Server2StatusChanged?.Invoke(this, true);
            }
            catch (Exception)
            {
                Stop();
                throw;
            }
        }

        /// <summary>
        /// 停止转发服务
        /// </summary>
        public void Stop()
        {
            if (isDisposed)
                return;

            server1.Stop();
            Server1StatusChanged?.Invoke(this, false);

            server2.Stop();
            Server2StatusChanged?.Invoke(this, false);
        }

        /// <summary>
        /// 检查端口是否可用
        /// </summary>
        public static bool IsPortAvailable(int port)
        {
            var listener = new System.Net.Sockets.TcpListener(System.Net.IPAddress.Any, port);
            try
            {
                listener.Start();
                return true;
            }
            catch
            {
                return false;
            }
            finally
            {
                listener.Stop();
            }
        }

        public void Dispose()
        {
            if (isDisposed)
                return;

            Stop();
            isDisposed = true;
        }
    }
} 